using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using BTV.TVAnyTime;
using TVAnyTimeClassLibrary;
using System.Data;

namespace BTV.Base
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1705:LongAcronymsShouldBePascalCased")]
    public class BTVDatabase
    {
        private Dictionary<string, BTVProgram> _programs = new Dictionary<string, BTVProgram>();

        public Dictionary<string, BTVProgram> Programs
        {
            get { return _programs; }
            //set { programs = value; }
        }

        private bool ProgramsListIsDirty = true;
        private List<BTVProgram> _programsList;

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
        public List<BTVProgram> ProgramsList
        {
            get
            {
                if (!ProgramsListIsDirty && _programsList != null)
                {
                    return _programsList;
                }
                else
                {
                    _programsList = new List<BTVProgram>();
                    foreach (KeyValuePair<string, BTVProgram> kvp in Programs)
                    {
                        _programsList.Add(kvp.Value);
                    }
                    ProgramsListIsDirty = false;
                    return _programsList;
                }
            }
        }
        /**
         * format of below:
         * --------------channelID-----------date------scheds-----
         */
        private Dictionary<string, Dictionary<DateTime, List<BTVSchedule>>> _schedules = new Dictionary<string, Dictionary<DateTime, List<BTVSchedule>>>();

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public Dictionary<string, Dictionary<DateTime, List<BTVSchedule>>> Schedules
        {
            get { return _schedules; }
            //set { schedules = value; }
        }
        private Dictionary<string, BTVChannel> _channels = new Dictionary<string, BTVChannel>();

        public Dictionary<string, BTVChannel> Channels
        {
            get { return _channels; }
        }
        private Dictionary<string, BTVChannel> _shownChannels = new Dictionary<string, BTVChannel>();

        public Dictionary<string, BTVChannel> ShownChannels
        {
            get { return _shownChannels; }
        }

        /**
         * format of below:
         * ---------------channelid-----------date----loaded-----
         */
        private Dictionary<string, Dictionary<string, bool>> _loadedSchedule = new Dictionary<string,Dictionary<string,bool>>();

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public Dictionary<string, Dictionary<string, bool>> LoadedSchedule
        {
          get { return _loadedSchedule; }
          set { _loadedSchedule = value; }
        }

        public void AddLoadedSchedule(string channelId, string dateTime)
        {
            Dictionary<string, bool> data;
            if (LoadedSchedule.TryGetValue(channelId, out data))
            {
                bool value;
                if (data.TryGetValue(dateTime, out value))
                {
                    value = true;
                }
                else
                {
                    data.Add(dateTime, true);
                }
            }
            else
            {
                data = new Dictionary<string, bool>();
                data.Add(dateTime, true);
                LoadedSchedule.Add(channelId, data);
            }
        }

        public bool IsScheduleLoaded(string channelId, string dateTime)
        {
            Dictionary<string, bool> data;
            if (LoadedSchedule.TryGetValue(channelId, out data))
            {
                bool value;
                if (data.TryGetValue(dateTime, out value))
                {
                    return value;
                }
            }
            return false;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
        public List<BTVChannel> ShownChannelsAsList
        {
            get
            {
                List<BTVChannel> l = new List<BTVChannel>();
                foreach (BTVChannel c in _shownChannels.Values)
                    l.Add(c);
                return l;
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "argEx")]
        public void AddProgram(BTVProgram p)
        {
            try
            {
                _programs.Add(p.PID, p);
                ProgramsListIsDirty = true;
            }
            catch  { }
        }

        public void Reset()
        {
            //programs = new Dictionary<string, TVAny_Program>();
            //schedules = new Dictionary<string, Dictionary<DateTime, ArrayList>>();
            _channels.Clear();
            _programs.Clear();
            _schedules.Clear();
            ResetShownChannels();
        }

        public void AddSchedule(BTVSchedule s, string channelId)
        {
            //Console.WriteLine("Adding schedule for " + channelID + " on " + s.start);
            Dictionary<DateTime, List<BTVSchedule>> d = new Dictionary<DateTime, List<BTVSchedule>>();
            List<BTVSchedule> d2 = new List<BTVSchedule>();
            if (_schedules.TryGetValue(channelId, out d))
            {
                if (d.TryGetValue(s.GetDay(), out d2))
                {
                    d2.Add(s);
                }
                else
                {
                    d2 = new List<BTVSchedule>();
                    d2.Add(s);
                    d.Add(s.GetDay(), d2);
                }
            }
            else
            {
                d = new Dictionary<DateTime, List<BTVSchedule>>();
                d2 = new List<BTVSchedule>();
                d2.Add(s);
                d.Add(s.GetDay(), d2);
                _schedules.Add(channelId, d);
            }
        }

        public BTVChannel GetChannelSchedule(string channelId, DateTime date)
        {
            BTVChannel c = new BTVChannel();
            c.Name = GetChannelById(channelId).Name;
            Dictionary<DateTime, List<BTVSchedule>> d = new Dictionary<DateTime, List<BTVSchedule>>();
            List<BTVSchedule> d2 = new List<BTVSchedule>();
            if (_schedules.TryGetValue(channelId, out d))
            {
                if (d.TryGetValue(date, out d2))
                {
                    foreach (BTVSchedule sched in d2)
                    {
                        c.AddSchedule(sched);
                        c.AddProgram(this.GetProgram(sched.Pid));
                    }
                }
            }

            return c;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
        public List<BTVSchedule> GetProgramSchedules(string crid)
        {
            List<BTVSchedule> sched = new List<BTVSchedule>();
            foreach (KeyValuePair<String, Dictionary<DateTime, List<BTVSchedule>>> kvp in _schedules)
            {
                foreach (KeyValuePair<DateTime, List<BTVSchedule>> kvp2 in kvp.Value)
                {
                    foreach (BTVSchedule s in kvp2.Value)
                    {
                        if (s.Pid == crid)
                        {
                            sched.Add(s);
                        }
                    }
                }
            }
            return sched;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public BTVScheduleSelection GetSeries(string seriesId)
        {
            BTVScheduleSelection d = new BTVScheduleSelection();
            foreach (KeyValuePair<string, BTVProgram> kvp in _programs)
            {
                if (kvp.Value.Series == seriesId)
                {
                    List<BTVSchedule> r = GetProgramSchedules(kvp.Key);
                    d.Add(new BTVProgramSchedule(kvp.Value, r));
                }
            }
            return d;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "t"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
        public List<BTVProgram> GetProgramsRelatedByGenre()
        {
            List<BTVProgram> relatedProgs = new List<BTVProgram>();
            foreach (KeyValuePair<string, BTVProgram> kvp in _programs)
            {
                if (typeof(TVAnyProgram) == kvp.Value.GetType())
                {
                    TVAnyProgram t = (TVAnyProgram)kvp.Value;
                    
                }
            }
            return relatedProgs;
        }

        public BTVProgram GetProgram(string pid)
        {
            BTVProgram p = new BTVProgram();
            if (_programs.TryGetValue(pid, out p))
            {
                return p;
            }
            else
            {
                return null;
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "argEx")]
        public void AddChannel(BTVChannel c){
            try
            {
                _channels.Add(c.Name, c);
            }
            catch 
            {
                //channel already exists
            }
        }

        public BTVChannel GetChannelByName(string name)
        {
            return _channels[name];
        }

        public BTVChannel GetChannelById(string id)
        {
            foreach ( BTVChannel c in _channels.Values )
            {
                if ( c.Id == id )
                {
                    return c;
                }
            }
            return null;
        }

        public void AddShownChannel(BTVChannel c){
            _shownChannels.Add(c.Name, GetChannelByName(c.Name));
        }

        public BTVChannel GetShownChannelByName(string name)
        {
            return _shownChannels[name];
        }


        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
        public void LoadShownChannels(List<BTVChannel> l)
        {
            foreach ( BTVChannel c in l )
            {
                AddShownChannel(c);
            }
        }

        public void ResetShownChannels()
        {
            _shownChannels.Clear();
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public BTVScheduleSelection GetProgramsByGenre(GenreType genre)
        {
            return GetProgramsByGenre(genre, 50);
        }

        public BTVScheduleSelection GetProgramsByGenre(GenreType genre, int count)
        {
            BTVScheduleSelection d = new BTVScheduleSelection();
            foreach ( KeyValuePair<string, BTVProgram> kvp in _programs )
            {
                if ( count <= 0 )
                    break;
                if ( typeof(TVAnyProgram) == kvp.Value.GetType() )
                {
                    TVAnyProgram t = (TVAnyProgram)kvp.Value;
                    if ( t.HasGenre(genre) )
                    {
                        count--;
                        List<BTVSchedule> r = GetProgramSchedules(kvp.Key);
                        d.Add(new BTVProgramSchedule(kvp.Value, r));
                    }
                }
            }
            return d;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public BTVScheduleSelection GetProgramsByKeyword(KeywordType kw)
        {
            return GetProgramsByKeyword(kw, 50);
        }

        public BTVScheduleSelection GetProgramsByKeyword(KeywordType kw, int count)
        {
            BTVScheduleSelection d = new BTVScheduleSelection();
            foreach (KeyValuePair<string, BTVProgram> kvp in _programs)
            {
                if (count <= 0)
                    break;
                if (typeof(TVAnyProgram) == kvp.Value.GetType())
                {
                    TVAnyProgram t = (TVAnyProgram)kvp.Value;
                    if (t.HasKeyword(kw))
                    {
                        count--;
                        List<BTVSchedule> r = GetProgramSchedules(kvp.Key);
                        d.Add(new BTVProgramSchedule(kvp.Value, r));
                    }
                }
            }
            return d;
        }

        public BTVProgramSchedulePairCollection GetNowAndNextPair(string crid)
        {
            BTVProgramSchedulePairCollection paircoll = new BTVProgramSchedulePairCollection();
            DateTime now = DateTime.Now;
            DateTime today = new DateTime(now.Year, now.Month, now.Day);
            BTVChannel c = GetChannelSchedule(crid, today);
            BTVSchedule nowS = null;
            BTVSchedule nextS = null;
            BTVProgram nowP;
            BTVProgram nextP;
            bool getNext = false;
            long ticks = 0;
            foreach (List<BTVSchedule> s in c.Schedules.Values)
            {
                foreach (BTVSchedule sched in s)
                {
                    if (getNext)
                    {
                        if (sched.StartTime.Ticks <= ticks && sched.EndTime.Ticks >= ticks)
                        {
                            nextS = sched;
                        }
                    }
                    else
                    {
                        if (sched.StartTime.Ticks <= now.Ticks && sched.EndTime.Ticks >= now.Ticks)
                        {
                            nowS = sched;
                            getNext = true;
                            ticks = sched.EndTime.Ticks;
                        }
                    }
                }
            }

            if (nowS != null)
            {
                nowP = c.GetProgram(nowS.Pid);
                if (nowP != null)
                {
                    BTVProgramSchedulePair nowPair = new BTVProgramSchedulePair(nowP, nowS);
                    paircoll.Add(nowPair);
                }
            }
            if (nextS != null)
            {
                nextP = c.GetProgram(nextS.Pid);
                if (nextP != null)
                {
                    BTVProgramSchedulePair nextPair = new BTVProgramSchedulePair(nextP, nextS);
                    paircoll.Add(nextPair);
                }
            }

            return paircoll;
        }

        public DataTable GetNowAndNext(string crid)
        {
            DateTime now = DateTime.Now;
            DateTime today = new DateTime(now.Year, now.Month, now.Day);
            BTVChannel c = GetChannelSchedule(crid, today);

            DataTable dt = new DataTable("Now && Next For " + c.Name);
            dt.Columns.Add("Program", typeof(BTVProgram));
            dt.Columns.Add("Schedule", typeof(BTVSchedule));
            dt.Columns.Add("Now", typeof(bool));

            BTVSchedule nowS = null;
            BTVSchedule nextS = null;
            BTVProgram nowP;
            BTVProgram nextP;
            bool getNext = false;
            long ticks = 0;
            foreach (List<BTVSchedule> s in c.Schedules.Values)
            {
                foreach (BTVSchedule sched in s)
                {
                    if (getNext)
                    {
                        if (sched.StartTime.Ticks <= ticks && sched.EndTime.Ticks >= ticks)
                        {
                            nextS = sched;
                        }
                    }
                    else
                    {
                        if (sched.StartTime.Ticks <= now.Ticks && sched.EndTime.Ticks >= now.Ticks)
                        {
                            nowS = sched;
                            getNext = true;
                            ticks = sched.EndTime.Ticks;
                        }
                    }
                }
            }

            if (nowS != null)
            {
                nowP = c.GetProgram(nowS.Pid);
                if (nowP != null)
                {
                    dt.Rows.Add(nowP, nowS, true);
                }
            }
            if (nextS != null)
            {
                nextP = c.GetProgram(nextS.Pid);
                if (nextP != null)
                {
                    dt.Rows.Add(nextP, nextS, false);
                }
            }
            return dt;
        }

        private Dictionary<TVAnyTimeClassLibrary.PersonType, BTVProgram> _actors;

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public Dictionary<TVAnyTimeClassLibrary.PersonType, BTVProgram> Actors
        {
            get { return _actors; }
            set { _actors = value; }
        }
    }
}
